# -*- coding:utf-8 -*-
# /views/fronted.py    前端视图

from flask import *
from flask_sqlalchemy import *
import json
import datetime

from exts import *
from tools import *


fronted = Blueprint("fronted", __name__, template_folder = "templates")


@fronted.route("/")
def index():
    template_data = {
        "global": {
            "name": Setting.query.filter(Setting.key == "oj_name").first().value,
            "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
        },
        "general": {
            "title": "主页",
            "subtitle": "",
            "user": is_login()
        },
        "private": {
            "notice": Setting.query.filter(Setting.key == "notice_html").first().value
        }
    }
    return render_template("fronted/index.html", **template_data)


@fronted.route("/problem/list/<page>")
def problem_list(page):
    total_page = ceil(Problem.query.count() / 10)
    if total_page == 0:
        abort(404)
    if int(page) < 1 or int(page) > total_page:
        abort(404)
    last_button_url = url_for("fronted.problem_list", page = int(page) - 1)
    next_botton_url = url_for("fronted.problem_list", page = int(page) + 1)
    if int(page) == 1:
        last_button_url = False
    if int(page) == total_page:
        next_botton_url = False
    template_data = {
        "global": {
            "name": Setting.query.filter(Setting.key == "oj_name").first().value,
            "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
        },
        "general": {
            "title": "题目",
            "subtitle": "",
            "user": is_login()
        },
        "private": {
            "problems": Problem.query.filter(Problem.id.between((int(page) - 1) * 10, int(page)*10)),
            "last_button_url": last_button_url,
            "next_button_url": next_botton_url
        }
    }
    return render_template("fronted/problem_list.html", **template_data)


@fronted.route("/problem/show/<problem_id>", methods = ["GET", "POST"])
def problem_show(problem_id):
    problem = Problem.query.filter(Problem.id == problem_id).first()
    if not problem:
        abort(404)
    user = is_login()
    if request.method == "GET":
        template_data = {
            "global": {
                "name": Setting.query.filter(Setting.key == "oj_name").first().value,
                "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
            },
            "general": {
                "title": "#" + problem_id + " " + problem.name,
                "subtitle": "",
                "user": user
            },
            "private": {
                "problem": problem
            }
        }
        return render_template("fronted/problem_show.html", **template_data)
    else:
        if not user:
            return redirect(url_for("fronted.user_login"))
        input_language = request.form.get("language")
        input_code = request.form.get("code")
        if input_language not in ["cpp", "c", "pascal"]:
            template_data = {
                "global": {
                    "name": Setting.query.filter(Setting.key == "oj_name").first().value,
                    "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
                },
                "general": {
                    "title": "#" + problem_id + " " + problem.name,
                    "subtitle": "",
                    "user": user
                },
                "private": {
                    "problem": problem
                }
            }
            return render_template("fronted/problem_show.html", **template_data, wrong = "未知的程序语言")
        count = Record.query.count() + 1
        record = Record(id = count,
                        user = user.username,
                        prob_id = problem_id,
                        language = input_language,
                        code = input_code,
                        status = "Waiting",
                        time = str(datetime.datetime.now())
                        )
        task = Task(task_id = count,
                    prob_id = problem_id,
                    language = input_language,
                    code = input_code
                    )
        db.session.add(record)
        db.session.add(task)
        db.session.commit()
        return redirect(url_for("fronted.record_show", record_id = count))


@fronted.route("/problem/answer/<problem_id>")
def problem_answer(problem_id):
    template_data = {
        "global": {
            "name": Setting.query.filter(Setting.key == "oj_name").first().value,
            "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
        },
        "general": {
            "title": "题解 #" + problem_id,
            "subtitle": "",
            "user": is_login()
        },
        "private": {
            "answer": Problem.query.filter(Problem.id == problem_id).first().answer_html
        }
    }
    return render_template("fronted/problem_answer.html", **template_data)


@fronted.route("/user/register", methods = ["GET", "POST"])
def user_register():
    if request.method == "GET":
        template_data = {
            "global": {
                "name": Setting.query.filter(Setting.key == "oj_name").first().value,
                "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
            },
            "general": {
                "title": "注册",
                "subtitle": ""
            }
        }
        return render_template("fronted/user_register.html", **template_data)
    else:
        input_username = request.form.get("username")
        input_password = request.form.get("password")
        input_password_r = request.form.get("passwordr")
        message = ""
        if len(input_username) == 0 or len(input_username) > 30:
            message = "用户名长度不符合要求"
        elif input_password != input_password_r:
            message = "两次密码不相同"
        elif User.query.filter(User.username == input_username).first():
            message = "用户名已存在"
        if message == "":
            user = User(username = input_username, password = sha512(input_password))
            db.session.add(user)
            db.session.commit()
            return redirect(url_for("fronted.user_login"))
        else:
            template_data = {
                "global": {
                    "name": Setting.query.filter(Setting.key == "oj_name").first().value,
                    "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
                },
                "general": {
                    "title": "注册",
                    "subtitle": ""
                }
            }
            return render_template("fronted/user_register.html", **template_data, message = message)


@fronted.route("/user/login", methods = ["GET", "POST"])
def user_login():
    if request.method == "GET":
        template_data = {
            "global": {
                "name": Setting.query.filter(Setting.key == "oj_name").first().value,
                "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
            },
            "general": {
                "title": "登录",
                "subtitle": ""
            }
        }
        return render_template("fronted/user_login.html", **template_data)
    else:
        input_username = request.form.get("username")
        input_password = request.form.get("password")
        user = User.query.filter(User.username == input_username).first()
        if not user or user.password != sha512(input_password):
            template_data = {
                "global": {
                    "name": Setting.query.filter(Setting.key == "oj_name").first().value,
                    "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
                },
                "general": {
                    "title": "登录",
                    "subtitle": ""
                }
            }
            return render_template("fronted/user_login.html", **template_data, wrong = True)
        else:
            session["user"] = user.username
            session["login"] = user.password
            return redirect(url_for("fronted.index"))


@fronted.route("/user/logout")
def user_logout():
    username = session.get("user", default = None)
    if username:
        session["user"] = None
    return redirect(url_for("fronted.index"))


@fronted.route("/user/setting", methods = ["GET", "POST"])
def user_setting():
    user = is_login()
    if not user:
        return redirect(url_for("fronted.user_login"))
    if request.method == "GET":
        template_data = {
            "global": {
                "name": Setting.query.filter(Setting.key == "oj_name").first().value,
                "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
            },
            "general": {
                "title": "用户设置",
                "subtitle": "",
                "user": user
            },
            "private": {

            }
        }
        return render_template("fronted/user_setting.html", **template_data, wrong = True)
    else:
        message_password = None
        input_password_old = request.form.get("password_old")
        input_password_new = request.form.get("password_new")
        input_password_rep = request.form.get("password_rep")
        if input_password_old != "":
            if sha512(input_password_old) != user.password:
                message_password = "原密码错误"
            elif input_password_new != input_password_rep:
                message_password = "两次密码输入不一致"
            else:
                user.password = sha512(input_password_new)
                db.session.commit()
        template_data = {
            "global": {
                "name": Setting.query.filter(Setting.key == "oj_name").first().value,
                "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
            },
            "general": {
                "title": "设置",
                "subtitle": "",
                "user": user
            },
            "private": {
                "password_message": message_password
            }
        }
        return render_template("fronted/user_setting.html", **template_data)


@fronted.route("/record/list/<page>")
def record_list(page):
    total_record = Record.query.count()
    if total_record == 0:
        abort(404)
    total_page = ceil(total_record / 10)
    if int(page) < 1 or int(page) > total_page:
        abort(404)
    last_button_url = url_for("fronted.record_list", page = int(page) - 1)
    next_button_url = url_for("fronted.record_list", page = int(page) + 1)
    if int(page) == 1:
        last_button_url = False
    if int(page) == total_page:
        next_button_url = False
    template_data = {
        "global": {
            "name": Setting.query.filter(Setting.key == "oj_name").first().value,
            "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
        },
        "general": {
            "title": "评测记录",
            "subtitle": "",
            "user": is_login()
        },
        "private": {
            "records":
                Record.query.filter(
                    Record.id.between(
                        total_record - int(page) * 10 + 1,
                        total_record - (int(page) - 1) * 10
                    )
                ).order_by(Record.id.desc()),
            "last_button_url": last_button_url,
            "next_button_url": next_button_url
        }
    }
    return render_template("fronted/record_list.html", **template_data)


@fronted.route("record/show/<record_id>")
def record_show(record_id):
    user = is_login()
    if not user:
        return redirect(url_for("fronted.user_login"))
    record = Record.query.filter(Record.id == record_id).first()
    if not record.result:
        template_data = {
            "global": {
                "name": Setting.query.filter(Setting.key == "oj_name").first().value,
                "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
            },
            "general": {
                "title": "评测记录",
                "subtitle": "",
                "user": user
            },
            "private": {
                "record": record,
                "record_prob": Problem.query.filter(Problem.id == record.prob_id).first(),
                "code_html": markdown_to_html("```" + record.language + "\r\n" + record.code + "\r\n```")
            }
        }
        return render_template("fronted/record_show.html", **template_data, complete = False)
    template_data = {
        "global": {
            "name": Setting.query.filter(Setting.key == "oj_name").first().value,
            "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
        },
        "general": {
            "title": "评测记录",
            "subtitle": "",
            "user": user
        },
        "private": {
            "record": record,
            "record_prob": Problem.query.filter(Problem.id == record.prob_id).first(),
            "result": json.loads(record.result),
            "code_html": markdown_to_html("```" + record.language + "\r\n" + record.code + "\r\n```")
        }
    }
    return render_template("fronted/record_show.html", **template_data, complete = True)


@fronted.route("/discuss/new/<board_name>", methods = ["GET", "POST"])
def discuss_new(board_name):
    user = is_login()
    if not user:
        return redirect(url_for("fronted.user_login"))
    board = Board.query.filter(Board.name == board_name).first()
    if not board:
        abort(404)
    if request.method == "GET":
        template_data = {
            "global": {
                "name": Setting.query.filter(Setting.key == "oj_name").first().value,
                "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
            },
            "general": {
                "title": "发布讨论",
                "subtitle": "",
                "user": is_login()
            },
            "private": {
                "board_name": board_name
            }
        }
        return render_template("fronted/discuss_new.html", **template_data)
    else:
        input_title = request.form.get("title", default = "")
        input_content = request.form.get("content", default = "")
        message = ""
        if input_title == "" or input_content == "":
            message = "标题或内容不能为空"
        elif len(input_title) > 30:
            message = "标题过长"
        if message != "":
            template_data = {
                "global": {
                    "name": Setting.query.filter(Setting.key == "oj_name").first().value,
                    "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
                },
                "general": {
                    "title": "发布讨论",
                    "subtitle": "",
                    "user": is_login()
                },
                "private": {
                    "board_name": board_name
                }
            }
            return render_template("fronted/discuss_new.html", **template_data, message = message)
        discuss = Discuss(
            id = Discuss.query.count() + 1,
            title = input_title,
            content = markdown_to_html(input_content),
            time = str(datetime.datetime.now()),
            user = user.username,
            comment = "[]",
            board = board.name
        )
        db.session.add(discuss)
        discuss_id_list = json.loads(board.discuss)
        discuss_id_list.append(discuss.id)
        board.discuss = json.dumps(discuss_id_list)
        db.session.commit()
        return redirect(url_for("fronted.discuss_show", discuss_id = discuss.id))


@fronted.route("/discuss/list/<page>")
def discuss_list(page):
    total_discuss = Discuss.query.count()
    if total_discuss == 0:
        template_data = {
            "global": {
                "name": Setting.query.filter(Setting.key == "oj_name").first().value,
                "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
            },
            "general": {
                "title": "讨论列表",
                "subtitle": "",
                "user": is_login()
            },
            "private": {
                "boards": json.loads(Setting.query.filter(Setting.key == "board").first().value)
            }
        }
        return render_template("fronted/discuss_list.html", **template_data)
    total_page = ceil(total_discuss / 10)
    if int(page) < 1 or int(page) > total_page:
        return render_template("err_404.html")
    last_button_url = url_for("fronted.discuss_list", page = int(page) - 1)
    next_button_url = url_for("fronted.discuss_list", page = int(page) + 1)
    if int(page) == 1:
        last_button_url = False
    if int(page) == total_page:
        next_button_url = False
    template_data = {
        "global": {
            "name": Setting.query.filter(Setting.key == "oj_name").first().value,
            "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
        },
        "general": {
            "title": "讨论列表",
            "subtitle": "",
            "user": is_login()
        },
        "private": {
            "discuss":
                Discuss.query.filter(
                    Discuss.id.between(
                        total_discuss - int(page) * 10 + 1,
                        total_discuss - (int(page) - 1) * 10
                    )
                ).order_by(Discuss.id.desc()),
            "last_button_url": last_button_url,
            "next_button_url": next_button_url,
            "boards": json.loads(Setting.query.filter(Setting.key == "board").first().value)
        }
    }
    return render_template("fronted/discuss_list.html", **template_data)


@fronted.route("/discuss/show/<discuss_id>", methods = ["GET", "POST"])
def discuss_show(discuss_id):
    discuss = Discuss.query.filter(Discuss.id == discuss_id).first()
    if not discuss:
        abort(404)
    if request.method == "GET":
        template_data = {
            "global": {
                "name": Setting.query.filter(Setting.key == "oj_name").first().value,
                "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
            },
            "general": {
                "title": "讨论:" + discuss.title,
                "subtitle": "",
                "user": is_login()
            },
            "private": {
                "discuss": discuss
            }
        }
        return render_template("fronted/discuss_show.html", **template_data)
    user = is_login()
    if not user:
        return redirect(url_for("fronted.user_login"))
    input_comment_content = request.form.get("comment_content")
    if input_comment_content == "":
        template_data = {
            "global": {
                "name": Setting.query.filter(Setting.key == "oj_name").first().value,
                "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
            },
            "general": {
                "title": "讨论:" + discuss.title,
                "subtitle": "",
                "user": is_login()
            },
            "private": {
                "discuss": discuss
            }
        }
        return render_template("fronted/discuss_show.html", **template_data, message = "评论内容不能为空")
    comment = Comment(
        id = Comment.query.count() + 1,
        content = input_comment_content,
        user = user.username,
        time = str(datetime.datetime.now())
    )
    db.session.add(comment)
    comment_id_list = json.loads(discuss.comment)
    comment_id_list.append(comment.id)
    discuss.comment = json.dumps(comment_id_list)
    db.session.commit()
    return redirect(url_for("fronted.discuss_show", discuss_id = discuss_id))


@fronted.route("/comment/list/<discuss_id>/<page>")
def comment_list(discuss_id, page):
    discuss = Discuss.query.filter(Discuss.id == discuss_id).first()
    if not discuss:
        abort(404)
    comment_id_list = json.loads(discuss.comment)
    comment_obj_list = []
    cnt_comment = len(comment_id_list)
    if cnt_comment == 0:
        return render_template("fronted/comment_list.html")
    comment_id_list = comment_id_list[max(cnt_comment - 10 * int(page), 0): cnt_comment - 10 * int(page) + 10]
    comment_id_list.reverse()
    for comment_id in comment_id_list:
        comment_obj_list.append(Comment.query.filter(Comment.id == comment_id).first())
    button = [
        url_for("fronted.comment_list", discuss_id = discuss_id, page = int(page) - 1),
        url_for("fronted.comment_list", discuss_id = discuss_id, page = int(page) + 1)
    ]
    if int(page) == 1:
        button[0] = None
    if int(page) == ceil(cnt_comment / 10):
        button[1] = None
    return render_template("fronted/comment_list.html", comments = comment_obj_list, button = button)


@fronted.route("/discuss/board/<board_name>/<page>")
def discuss_board(board_name, page):
    board = Board.query.filter(Board.name == board_name).first()
    if not board:
        abort(404)
    discuss_id_list = json.loads(board.discuss)
    cnt_discuss = len(discuss_id_list)
    if cnt_discuss == 0:
        template_data = {
            "global": {
                "name": Setting.query.filter(Setting.key == "oj_name").first().value,
                "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
            },
            "general": {
                "title": "讨论版：" + board_name,
                "subtitle": "",
                "user": is_login()
            },
            "private": {
                "board_name": board_name
            }
        }
        return render_template("fronted/discuss_board.html", **template_data)
    discuss_id_list = discuss_id_list[max(cnt_discuss - 10 * int(page), 0): cnt_discuss - 10 * int(page) + 10]
    discuss_id_list.reverse()
    discuss_obj_list = []
    for discuss_id in discuss_id_list:
        discuss_obj_list.append(Discuss.query.filter(Discuss.id == discuss_id).first())
    button = [
        url_for("fronted.discuss_board", board_name = board_name, page = int(page) - 1),
        url_for("fronted.discuss_board", board_name = board_name, page = int(page) + 1)
    ]
    if int(page) == 1:
        button[0] = None
    if int(page) == ceil(cnt_discuss / 10):
        button[1] = None
    template_data = {
        "global": {
            "name": Setting.query.filter(Setting.key == "oj_name").first().value,
            "abb_name": Setting.query.filter(Setting.key == "oj_name_abb").first().value
        },
        "general": {
            "title": "讨论版：" + board_name,
            "subtitle": "",
            "user": is_login()
        },
        "private": {
            "board_name": board_name,
            "discuss_list": discuss_obj_list,
            "button": button
        }
    }
    return render_template("fronted/discuss_board.html", **template_data)


def is_login():
    username = session.get("user", default = None)
    user_password = session.get("login", default = None)
    if username and user_password:
        user = User.query.filter(User.username == username).first()
        if user and user_password == user.password:
            return user
        else:
            return None
    else:
        return None
